<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>课时12_装饰器模式</title>
</head>

<body>
    <div class="course-content">
        <div class="current-component">
            <div class="text markdown-body">
                <div>
                    <h1
                        style="border:0px;margin:0px 0px 10px;padding:0px;font-size:2.1em;font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        装饰器模式</h1>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        装饰器模式（Decorator Pattern）允许向一个现有的对象添加新的功能，同时又不改变其结构。这种类型的设计模式属于结构型模式，它是作为现有的类的一个包装。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        这种模式创建了一个装饰类，用来包装原有的类，并在保持类方法签名完整性的前提下，提供了额外的功能。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        我们通过下面的实例来演示装饰器模式的用法。其中，我们将把一个形状装饰上不同的颜色，同时又不改变形状类。</p>

                    <h2 class="tutheader"
                        style="border-width:1px 0px 0px;border-top-style:solid;border-top-color:rgb(212,212,212);margin:0px;padding:5px 0px 0px;font-size:1.8em;line-height:1.8em;clear:both;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        介绍</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>意图：</strong>动态地给一个对象添加一些额外的职责。就增加功能来说，装饰器模式相比生成子类更为灵活。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>主要解决：</strong>一般的，我们为了扩展一个类经常使用继承方式实现，由于继承为类引入静态特征，并且随着扩展功能的增多，子类会很膨胀。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>何时使用：</strong>在不想增加很多子类的情况下扩展类。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>如何解决：</strong>将具体功能职责划分，同时继承装饰者模式。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>关键代码：</strong>&nbsp;1、Component 类充当抽象角色，不应该具体实现。 2、修饰类引用和继承 Component 类，具体扩展类重写父类方法。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>应用实例：</strong>&nbsp;1、孙悟空有 72 变，当他变成"庙宇"后，他的根本还是一只猴子，但是他又有了庙宇的功能。
                        2、不论一幅画有没有画框都可以挂在墙上，但是通常都是有画框的，并且实际上是画框被挂在墙上。在挂在墙上之前，画可以被蒙上玻璃，装到框子里；这时画、玻璃和画框形成了一个物体。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>优点：</strong>装饰类和被装饰类可以独立发展，不会相互耦合，装饰模式是继承的一个替代模式，装饰模式可以动态扩展一个实现类的功能。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>缺点：</strong>多层装饰比较复杂。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>使用场景：</strong>&nbsp;1、扩展一个类的功能。 2、动态增加功能，动态撤销。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <strong>注意事项：</strong>可代替继承。
                    </p>

                    <h2 class="tutheader"
                        style="border-width:1px 0px 0px;border-top-style:solid;border-top-color:rgb(212,212,212);margin:0px;padding:5px 0px 0px;font-size:1.8em;line-height:1.8em;clear:both;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        实现</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        我们将创建一个&nbsp;<em>Shape</em>&nbsp;接口和实现了&nbsp;<em>Shape</em>&nbsp;接口的实体类。然后我们创建一个实现了&nbsp;<em>Shape</em>&nbsp;接口的抽象装饰类<em>ShapeDecorator</em>，并把&nbsp;<em>Shape</em>&nbsp;对象作为它的实例变量。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>RedShapeDecorator</em>&nbsp;是实现了&nbsp;<em>ShapeDecorator</em>&nbsp;的实体类。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>DecoratorPatternDemo</em>，我们的演示类使用&nbsp;<em>RedShapeDecorator</em>&nbsp;来装饰&nbsp;<em>Shape</em>&nbsp;对象。
                    </p>

                    <p><img alt="" src="https://developer.aliyun.com/files/course/2017/09-24/1248044a2416827303.jpg"
                            data-spm-anchor-id="a2c6h.21258798.0.i9.16fd4cc3QN5WJm"></p>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 1</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建一个接口。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Shape.java</em>
                    </p>

                    <pre><code class="language-java">public interface Shape {
       void draw();}</code></pre>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 2</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建实现接口的实体类。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Rectangle.java</em>
                    </p>

                    <pre><code class="language-java">public class Rectangle implements Shape {
    
       @Override
       public void draw() {
          System.out.println("Shape: Rectangle");
       }}</code></pre>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Circle.java</em>
                    </p>

                    <pre><code class="language-java">public class Circle implements Shape {
    
       @Override
       public void draw() {
          System.out.println("Shape: Circle");
       }}</code></pre>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 3</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建实现了&nbsp;<em>Shape</em>&nbsp;接口的抽象装饰类。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>ShapeDecorator.java</em>
                    </p>

                    <pre><code class="language-java">public abstract class ShapeDecorator implements Shape {
       protected Shape decoratedShape;
    
       public ShapeDecorator(Shape decoratedShape){
          this.decoratedShape = decoratedShape;
       }
    
       public void draw(){
          decoratedShape.draw();
       }	}</code></pre>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 4</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建扩展了&nbsp;<em>ShapeDecorator</em>&nbsp;类的实体装饰类。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>RedShapeDecorator.java</em>
                    </p>

                    <pre><code class="language-java">public class RedShapeDecorator extends ShapeDecorator {
    
       public RedShapeDecorator(Shape decoratedShape) {
          super(decoratedShape);		
       }
    
       @Override
       public void draw() {
          decoratedShape.draw();	       
          setRedBorder(decoratedShape);
       }
    
       private void setRedBorder(Shape decoratedShape){
          System.out.println("Border Color: Red");
       }}</code></pre>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 5</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        使用&nbsp;<em>RedShapeDecorator</em>&nbsp;来装饰&nbsp;<em>Shape</em>&nbsp;对象。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>DecoratorPatternDemo.java</em>
                    </p>

                    <pre><code class="language-java">public class DecoratorPatternDemo {
       public static void main(String[] args) {
    
          Shape circle = new Circle();
    
          Shape redCircle = new RedShapeDecorator(new Circle());
    
          Shape redRectangle = new RedShapeDecorator(new Rectangle());
          System.out.println("Circle with normal border");
          circle.draw();
    
          System.out.println("\nCircle of red border");
          redCircle.draw();
    
          System.out.println("\nRectangle of red border");
          redRectangle.draw();
       }}</code></pre>

                    <h3
                        style="border:0px;margin:8px 0px;padding:0px;font-size:1.4em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 6</h3>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        验证输出。</p>

                    <pre><code class="language-vbscript">Circle with normal border
    Shape: Circle
    Circle of red border
    Shape: Circle
    Border Color: Red
    Rectangle of red border
    Shape: Rectangle
    Border Color: Red</code></pre>

                    <p>&nbsp;</p>
                </div>
            </div>
        </div>
    </div>
</body>

</html>